package com.rockcent.mall.lib.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.SQLListDoing;
import com.rockcent.common.common.SQLPageDoing;
import com.rockcent.common.utils.RDateUtils;
import com.rockcent.mall.lib.domain.MerchantFundFlow;
import com.rockcent.mall.lib.domain.enumclass.FundTransactionFlow;
import com.rockcent.mall.lib.domain.enumclass.MerchantFundFlowTransactionType;
import com.rockcent.mall.lib.domain.enumclass.MerchantPayType;
import com.rockcent.mall.lib.dto.MerchantFundDto;
import com.rockcent.mall.lib.dto.MerchantFundFlowDto;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by DK on 16/11/8.
 */
@Repository
public class MerchantFundFlowRepositoryImpl implements MerchantFundFlowRepositoryCustom {

    private static final Logger log = LoggerFactory.getLogger(MerchantFundFlowRepositoryImpl.class);

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public PageResult<MerchantFundFlowDto> findMerchantFundFlowPage(String transactionFlow, String transactionType, String merchantOrderNum,  String payType,String beginDate, String endDate, Long merchantId, Long mallId, PageResult pageResult) {
        SQLPageDoing<MerchantFundFlowDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from merchant_fund_flow mff join (select merchant_order_num, max(id) as id from merchant_fund_flow  b where 1=1 ");

            if (MerchantFundFlowTransactionType.ALL != MerchantFundFlowTransactionType.valueOf(transactionType)) {
                sql.append(" AND b.transaction_type = :transactionType");
                params.put("transactionType", transactionType);
            } else {
                sql.append(" AND b.transaction_type in(:transactionType)");
                params.put("transactionType", Arrays.asList(MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND.toString(),MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND.toString(), MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME.toString(), MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME.toString(), MerchantFundFlowTransactionType.A_RECHARGE_INCOME.toString(), MerchantFundFlowTransactionType.A_RECHARGE_PRESENTED.toString()));
            }

            sql.append(" group by b.merchant_order_num) b where mff.id=b.id and mff.merchant_order_num = b.merchant_order_num ");


            if (StringUtils.isNotBlank(merchantOrderNum)) {
                sql.append(" AND mff.merchant_order_num LIKE :merchantOrderNum");
                params.put("merchantOrderNum", "%" + merchantOrderNum + "%");
            }

            if (FundTransactionFlow.ALL != FundTransactionFlow.valueOf(transactionFlow)) {
                sql.append(" AND mff.transaction_flow = :transactionFlow");
                params.put("transactionFlow", transactionFlow);
            }

            if(StringUtils.isNotBlank(payType)){
                if (MerchantPayType.ALL != MerchantPayType.valueOf(payType)) {
                    sql.append(" AND mff.pay_type = :payType");
                    params.put("payType", payType);
                }
            }

            if (MerchantFundFlowTransactionType.ALL != MerchantFundFlowTransactionType.valueOf(transactionType)) {
                sql.append(" AND mff.transaction_type = :transactionType");
                params.put("transactionType", transactionType);
            } else {
                sql.append(" AND mff.transaction_type in(:transactionType)");
                params.put("transactionType", Arrays.asList(MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND.toString(),MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND.toString(), MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME.toString(), MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME.toString(), MerchantFundFlowTransactionType.A_RECHARGE_INCOME.toString(), MerchantFundFlowTransactionType.A_RECHARGE_PRESENTED.toString()));
            }

            if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate)) {
                sql.append(" AND mff.date_created < :endDate AND mff.date_created > :beginDate");
                params.put("beginDate", RDateUtils.beforeDateStr(beginDate, 0));
                params.put("endDate", RDateUtils.afterDateStr(endDate, 1));
            }
            sql.append(" AND mff.mall_id = :mallId");
            sql.append(" AND mff.merchant_id = :merchantId");
            params.put("mallId", mallId);
            params.put("merchantId", merchantId);
            sql.append(" ORDER BY mff.id desc");
            fields.append("mff.id, mff.transaction_flow, mff.transaction_type, mff.parent_id, mff.operation_amount, mff.merchant_order_num, mff.merchant_id, mff.mall_id, mff.frozen, mff.date_created, mff.last_updated, mff.total_amount,mff.pay_type,mff.remark");

        };
        return doing.go(pageResult, MerchantFundFlowDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public List<MerchantFundFlowDto> findMallMerchantFundFlowInfoExport(String transactionFlow, String transactionType, String merchantOrderNum, String beginDate, String endDate, Long merchantId, Long mallId) {
        SQLListDoing<MerchantFundFlowDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from merchant_fund_flow mff where 1=1 ");

            if (StringUtils.isNotBlank(merchantOrderNum)) {
                sql.append(" AND mff.merchant_order_num LIKE :merchantOrderNum");
                params.put("merchantOrderNum", "%" + merchantOrderNum + "%");
            }

            if (FundTransactionFlow.ALL == FundTransactionFlow.valueOf(transactionFlow)) {
                sql.append(" AND mff.transaction_flow = 'INCOME'");
                params.put("transactionFlow", transactionFlow);
            } else {
                sql.append(" AND mff.transaction_flow = :transactionFlow");
                params.put("transactionFlow", transactionFlow);
            }

            if (MerchantFundFlowTransactionType.ALL != MerchantFundFlowTransactionType.valueOf(transactionType)) {
                sql.append(" AND mff.transaction_type = :transactionType");
                params.put("transactionType", transactionType);
            } else {
                sql.append(" AND mff.transaction_type in(:transactionType)");
                params.put("transactionType", Arrays.asList(MerchantFundFlowTransactionType.A_ORDER_SERVICE_FEE_ARREARS_EXPEND.toString(),MerchantFundFlowTransactionType.A_APPLY_WITHDRAW_EXPEND.toString(), MerchantFundFlowTransactionType.A_ORDER_RESELL_FEE_INCOME.toString(), MerchantFundFlowTransactionType.A_ORDER_SETTLEMENT_INCOME.toString(), MerchantFundFlowTransactionType.A_RECHARGE_INCOME.toString(), MerchantFundFlowTransactionType.A_RECHARGE_PRESENTED.toString()));
            }

            if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate)) {
                sql.append(" AND mff.date_created < :endDate AND mff.date_created > :beginDate");
                params.put("beginDate", RDateUtils.beforeDateStr(beginDate, 0));
                params.put("endDate", RDateUtils.afterDateStr(endDate, 1));
            }
            sql.append(" AND mff.mall_id = :mallId");
            sql.append(" AND mff.merchant_id = :merchantId");
            params.put("mallId", mallId);
            params.put("merchantId", merchantId);
            sql.append(" ORDER BY mff.id  desc");
            fields.append("mff.date_created createDate, mff.id, mff.transaction_flow, mff.transaction_type, mff.parent_id, mff.operation_amount, mff.merchant_order_num, mff.merchant_id, mff.mall_id, mff.frozen, mff.date_created, mff.last_updated, mff.total_amount");
        };
        return doing.go(MerchantFundFlowDto.class, objectMapper, jdbcTemplate, log);
    }
}
